package de.fhffm.scs.simulator.food;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.joda.time.DateTime;
import org.joda.time.LocalTime;
import org.joda.time.Minutes;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import de.fhffm.scs.simulator.body.Body;
import de.fhffm.scs.simulator.scheduler.Scheduler;

public class FeedSimulator implements Runnable {

    private static Logger LOGGER = LoggerFactory.getLogger(FeedSimulator.class);

    private static DateTimeFormatter FORMAT = DateTimeFormat.forPattern("HH:mm");

    private static final List<String> FEED_TIMES = Arrays.asList("9:00", "12:30", "18:00");

    private Thread thread;

    private Scheduler scheduler;

    private Body body;

    public FeedSimulator(Body body, Scheduler scheduler) {
        this.body = body;
        this.scheduler = scheduler;
    }

    private List<String> todayFeeded = new ArrayList<String>();

    @Override
    public void run() {
        LOGGER.info("Simulation started");
        while (!thread.isInterrupted()) {
            try {
                DateTime now = nowByScheduler();
                DateTime nextFireTime = getNextFeedTime(now);
                int minutesToSleep = Minutes.minutesBetween(now, nextFireTime).getMinutes();
                LOGGER.debug("Next feed time is {}, sleep for {} minutes", nextFireTime, minutesToSleep);
                scheduler.sleep(TimeUnit.MINUTES, minutesToSleep);
                Aliment randomFood = pickRandomFood();
                Aliment randomDrink = pickRandomDrink();
                body.eatOrDrink(randomFood);
                body.eatOrDrink(randomDrink);
                LOGGER.info("Eat {} and {} (s={}mg)",
                    new Object[] { randomDrink, randomFood, randomDrink.getSugarInMg() + randomFood.getSugarInMg() });
            } catch (InterruptedException e) {
                thread.interrupt();
            }
        }
    }

    private Aliment pickRandomFood() {
        FoodSelection[] selection = FoodSelection.values();
        return selection[new Random().nextInt(selection.length)];
    }

    private Aliment pickRandomDrink() {
        DrinkSelection[] selection = DrinkSelection.values();
        return selection[new Random().nextInt(selection.length)];
    }

    private DateTime nowByScheduler() {
        return new DateTime(scheduler.getCurrentTimestamp());
    }

    private DateTime getNextFeedTime(DateTime now) {
        for (String feedTime : FEED_TIMES) {
            DateTime feedTimeToday = getTodayAtTime(feedTime);
            if (now.isBefore(feedTimeToday) && !todayFeeded.contains(feedTime)) {
                todayFeeded.add(feedTime);
                return getTodayAtTime(feedTime);
            }
        }
        // If it is too late, the next feed time is on the other day
        todayFeeded.clear();
        todayFeeded.add(FEED_TIMES.get(0));
        return getTodayAtTime(FEED_TIMES.get(0)).plusDays(1);
    }

    public void start() {
        thread = new Thread(this);
        thread.start();
    }

    public void stop() {
        try {
            thread.interrupt();
            thread.join();
        } catch (InterruptedException e) {
            // Nothing to do
        }
    }

    private DateTime getTodayAtTime(String time) {
        LocalTime localTime = FORMAT.parseLocalTime(time);
        return new DateTime(scheduler.getCurrentTimestamp()).withTime(localTime.getHourOfDay(),
            localTime.getMinuteOfHour(),
            localTime.getSecondOfMinute(), localTime.getMillisOfSecond());
    }

    public static void main(String[] args) {
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        System.out.println(lc.getLoggerList());
        lc.getLogger("asd");
    }

}
